package me.zhengjie.controller.test;

import me.zhengjie.dao.ContainerDao;
import me.zhengjie.dao.MaterialDao;
import me.zhengjie.dao.StoreLocalDao;
import me.zhengjie.utils.ExecutorUtil;
import me.zhengjie.utils.SnowIdUtil;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ExecutorService;

public class DataGenerator {
    private static final String[] WAREHOUSES = {"M1", "M2"};//, "M3", "M4"
    private static final String[] REGIONS = {"A", "B", "C", "D", "E", "F", "G"};
    private static final String[] WARE_TYPES = {"1", "2"};
    private static final String[] STORE_TYPES = {"料箱储位", "托盘储位"};
    private static final String[] GOOD_TYPES = {"2", "2", "2", "4"}; // "线边储位", "抽检区", "分拣区",
    private static final String[] CONTAINER_TYPES = {"料箱", "托盘"};
    private static final String[] CONTAINER_LOCATIONS = {"0", "1"};
    private static final String[] MATERIAL_CATEGORIES = {"1", "2"};
    private static final String[] MATERIAL_TYPES = {"在制品", "实体物料"};
    private static final String[] UNITS = {"件", "箱", "包", "捆", "千克", "米", "升"};
    private static final String[] COLORS = {"红色", "蓝色", "绿色", "黄色", "黑色", "白色", "灰色"};
    private static final String[] MEASUREMENT_METHODS = {"称重", "计件", "计长", "计体积"};
    private static final String[] PACKAGING_METHODS = {"纸箱包装", "木箱包装", "塑料袋包装", "托盘包装", "裸装"};
    private static final String[] OPERATORS = {"张三", "李四", "王五", "赵六", "钱七", "孙八", "周九", "吴十"};

    private static final List<String> MANUFACTURERS = Arrays.asList(
            "青岛海尔股份有限公司", "华为技术有限公司", "比亚迪电子股份有限公司",
            "富士康科技集团", "三星电子株式会社", "苹果公司", "LG电子",
            "索尼集团公司", "松下电器产业株式会社", "东芝公司", "西门子股份公司",
            "博世集团", "飞利浦公司", "3M公司", "通用电气公司", "丰田汽车公司",
            "大众汽车集团", "宝马集团", "奔驰汽车公司", "耐克公司", "阿迪达斯公司",
            "优衣库", "ZARA", "H&M", "可口可乐公司", "百事公司", "雀巢公司",
            "联合利华公司", "宝洁公司", "强生公司", "辉瑞制药有限公司", "默克公司",
            "诺华制药公司", "罗氏公司", "阿斯利康制药有限公司", "微软公司", "谷歌公司",
            "亚马逊公司", "脸书公司", "腾讯控股有限公司", "阿里巴巴集团控股有限公司",
            "百度公司", "字节跳动有限公司", "小米科技有限责任公司", "OPPO广东移动通信有限公司",
            "VIVO移动通信有限公司", "宁德时代新能源科技股份有限公司", "中芯国际集成电路制造有限公司",
            "台积电公司", "美光科技公司", "SK海力士公司", "西部数据公司", "希捷科技公司",
            "金士顿科技公司", "闪迪公司", "博通公司", "高通公司", "英特尔公司", "AMD公司",
            "英伟达公司", "戴尔科技公司", "惠普公司", "联想集团有限公司", "华硕电脑股份有限公司",
            "宏碁股份有限公司", "佳能公司", "尼康公司", "索尼影像产品公司", "松下电器产业株式会社",
            "夏普公司", "LG Display", "京东方科技集团股份有限公司", "TCL科技集团股份有限公司",
            "海信集团有限公司", "创维集团有限公司", "康佳集团股份有限公司", "长虹电器股份有限公司",
            "格力电器股份有限公司", "美的集团股份有限公司", "苏泊尔股份有限公司", "九阳股份有限公司",
            "小熊电器股份有限公司", "老板电器股份有限公司", "方太集团", "海尔智家股份有限公司",
            "海信视像科技股份有限公司", "TCL电子控股有限公司", "小米通讯技术有限公司", "荣耀终端有限公司",
            "中兴通讯股份有限公司", "大唐电信科技股份有限公司", "烽火通信科技股份有限公司", "长飞光纤光缆股份有限公司",
            "亨通光电股份有限公司", "通鼎互联信息股份有限公司", "中天科技集团有限公司", "海通集团股份有限公司",
            "华为终端有限公司", "苹果产品贸易（上海）有限公司", "三星（中国）投资有限公司", "LG电子（中国）有限公司",
            "索尼（中国）有限公司", "松下电器（中国）有限公司", "东芝（中国）有限公司", "西门子（中国）有限公司",
            "博世（中国）投资有限公司", "飞利浦（中国）投资有限公司", "3M中国有限公司", "通用电气（中国）有限公司",
            "丰田汽车（中国）投资有限公司", "大众汽车（中国）投资有限公司", "宝马（中国）汽车贸易有限公司", "梅赛德斯-奔驰（中国）汽车销售有限公司",
            "耐克体育（中国）有限公司", "阿迪达斯体育（中国）有限公司", "迅销（中国）商贸有限公司", "飒拉商业（北京）有限公司",
            "海恩斯莫里斯（上海）商业有限公司", "可口可乐（中国）饮料有限公司", "百事（中国）投资有限公司", "雀巢（中国）有限公司",
            "联合利华（中国）投资有限公司", "宝洁（中国）有限公司", "强生（中国）投资有限公司", "辉瑞制药有限公司",
            "默克雪兰诺有限公司", "诺华（中国）生物医学研究有限公司", "罗氏（中国）投资有限公司", "阿斯利康（中国）有限公司",
            "微软（中国）有限公司", "谷歌信息技术（中国）有限公司", "亚马逊（中国）投资有限公司", "脸书科技（中国）有限公司",
            "腾讯科技（深圳）有限公司", "阿里巴巴（中国）网络技术有限公司", "百度在线网络技术（北京）有限公司", "字节跳动（中国）有限公司",
            "小米科技有限责任公司", "OPPO广东移动通信有限公司", "VIVO移动通信有限公司", "宁德时代新能源科技股份有限公司",
            "中芯国际集成电路制造有限公司", "台积电（中国）有限公司", "美光半导体（西安）有限责任公司", "SK海力士半导体（中国）有限公司",
            "西部数据（中国）有限公司", "希捷科技（苏州）有限公司", "金士顿科技（中国）有限公司", "闪迪（中国）科技有限公司",
            "博通（中国）有限公司", "高通无线通信技术（中国）有限公司", "英特尔（中国）有限公司", "超威半导体（中国）有限公司",
            "英伟达半导体科技（上海）有限公司", "戴尔（中国）有限公司", "中国惠普有限公司", "联想（北京）有限公司", "华硕电脑（上海）有限公司",
            "宏碁电脑（上海）有限公司", "佳能（中国）有限公司", "尼康映像仪器销售（中国）有限公司", "索尼电子（中国）有限公司", "松下电器机电（中国）有限公司",
            "夏普办公设备（常熟）有限公司", "乐金显示（中国）有限公司", "京东方科技集团股份有限公司", "TCL华星光电技术有限公司",
            "海信电器营销股份有限公司", "创维数字技术（深圳）有限公司", "康佳集团股份有限公司", "四川长虹电器股份有限公司",
            "珠海格力电器股份有限公司", "美的集团股份有限公司", "浙江苏泊尔股份有限公司", "九阳股份有限公司",
            "小熊电器股份有限公司", "杭州老板电器股份有限公司", "宁波方太厨具有限公司", "海尔智家股份有限公司",
            "海信视像科技股份有限公司", "TCL电子控股有限公司", "小米通讯技术有限公司", "荣耀终端有限公司",
            "中兴通讯股份有限公司", "大唐电信科技股份有限公司", "烽火通信科技股份有限公司", "长飞光纤光缆股份有限公司",
            "江苏亨通光电股份有限公司", "通鼎互联信息股份有限公司", "中天科技集团有限公司", "海通集团股份有限公司"
    );

    private static final Random random = new Random();

    public static void main(String[] args) {
//        int containerCount = 1000;
//        int storeCount = 20000;
//        int materialCount = 4000000;
//        ExecutorService executorServer = ExecutorUtil.getExecutorUtil().getExecutorServer();
//        try {
//            // 生成载具数据
//            List<ContainerDao> containers = generateContainers(containerCount);
//            // 生成储位数据
//            List<StoreLocalDao> stores = generateStores(storeCount, containers);
//            // 生成物料数据
////            List<MaterialDao> materials = generateMaterials(materialCount, containers, stores);
//            for (int i = 0; i < 50; i++) {
//                int finalI = i;
//                executorServer.submit(() -> {
//                    try {
//                        int start = finalI * 10000+1;
//                        int end = (finalI + 1) * 10000;
//                        // 生成物料数据
//                        List<MaterialDao> materials = generateMaterials(start, end, containers, stores);
//
//                    } catch (Exception e) {
//                        System.out.println("****************1: " + e.getMessage());
//                    }
//                });
//
//            }
//            System.out.println("数据生成完成！");
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
    }

    public static List<ContainerDao> generateContainers(int count) {
        HashSet<String> hashSet = new HashSet<>();
        List<ContainerDao> containers = new ArrayList<>(count);
        for (int i = 1; i <= count; i++) {
            ContainerDao container = new ContainerDao();
            container.setId("C" + String.format("%05d", i));
            if (hashSet.contains(container.getId())) {
                continue;
            }
            hashSet.add(container.getId());
            container.setType(randomElement(CONTAINER_TYPES));
            container.setLocal(randomElement(CONTAINER_LOCATIONS));
            container.setDisable(random.nextInt(2));
            container.setIsExist(random.nextInt(2));
            container.setBarCodeBad(random.nextInt(2));
            container.setContainerBad(random.nextInt(2));

            // 异常状态时间（如果有异常）
            if (container.getBarCodeBad() == 1 || container.getContainerBad() == 1) {
                container.setAbnormalDate(new Timestamp(randomDate1(2020, 2025).getTime()));
            }

            container.setWeight(randomDouble(10, 1000));
            container.setCreateDate(new Timestamp(System.currentTimeMillis()));
            container.setUpdateDate(new Timestamp(System.currentTimeMillis()));
            container.setWLong(randomDouble(0.5, 2));
            container.setWWide(randomDouble(0.5, 2));
            container.setWTall(randomDouble(0.5, 2.5));

            containers.add(container);
        }
        return containers;
    }

    public static List<StoreLocalDao> generateStores(int count, List<ContainerDao> containers) {
        List<StoreLocalDao> stores = new ArrayList<>(count);

        // 每个仓库区域的储位数量
        int perWarehouseCount = count / WAREHOUSES.length;
        int perRegionCount = perWarehouseCount / REGIONS.length;

        int storeId = 1;
        int containerIndex = 0;

        HashSet<String> hashSet = new HashSet<>();
        for (String warehouse : WAREHOUSES) {
            for (String region : REGIONS) {
                for (int frame = 1; frame <= 10; frame++) {
                    for (int serial = 1; serial <= perRegionCount / 10; serial++) {
                        if (storeId > count) break;

                        StoreLocalDao store = new StoreLocalDao();
                        String id = warehouse + "-" + region + "-" + frame + "-" + serial;
                        store.setId(id);
                        store.setStoreName("储位_" + id);
                        store.setFloor(warehouse);
                        store.setRegion(region);
                        store.setFrame(String.valueOf(frame));
                        store.setSerial(String.valueOf(serial));
                        store.setWareType(randomElement(WARE_TYPES));
                        if (Objects.equals(warehouse, "M1")) {
                            store.setStoreType(STORE_TYPES[1]);
                        }
                        if (Objects.equals(warehouse, "M2")) {
                            store.setStoreType(STORE_TYPES[0]);
                        }
                        store.setGoodType(randomElement(GOOD_TYPES));
                        // 随机分配载具 (约30%的储位有载具)
                        boolean hasContainer = random.nextDouble() < 0.3;

                        if (hasContainer && containerIndex < containers.size()) {
                            ContainerDao container = containers.get(containerIndex++);
                            String id1 = container.getId();
                            if (hashSet.contains(id1)) {
                                store.setStatus(0); // 0-2: 空闲,入库,出库
                                store.setContainerCode("");
                            } else {
                                hashSet.add(id1);
                                store.setContainerCode(container.getId());
                                store.setStatus(3); // 有货
                            }
                        } else {
                            store.setStatus(0); // 0-2: 空闲,入库,出库
                            store.setContainerCode(null);
                        }

                        store.setIsLock(0);
                        store.setCreateDate(new Timestamp(System.currentTimeMillis()));
                        store.setUpdateDate(new Timestamp(System.currentTimeMillis()));
                        store.setWeight(randomDouble(100, 10000));
                        store.setSLong(randomDouble(0.8, 3));
                        store.setSWide(randomDouble(0.8, 3));
                        store.setSTall(randomDouble(1, 5));

                        stores.add(store);
                        storeId++;
                    }
                }
            }
        }
        return stores;
    }

    public static List<MaterialDao> generateMaterials(int start, int end, List<ContainerDao> containers, List<StoreLocalDao> stores) {
        List<MaterialDao> materials = new ArrayList<>(end - start + 1);

        // 按仓库分组的储位
        Map<String, List<StoreLocalDao>> storesByWarehouse = new HashMap<>();
        for (String warehouse : WAREHOUSES) {
            storesByWarehouse.put(warehouse, new ArrayList<>());
        }
        for (StoreLocalDao store : stores) {
            if (store.getContainerCode() != null) { // 只考虑有载具的储位
                storesByWarehouse.get(store.getFloor()).add(store);
            }
        }

        // 生成物料
        for (int i = start; i <= end; i++) {
            MaterialDao material = new MaterialDao();
            material.setItemBarCode("ITEM" + String.format("%08d", i));
            material.setMaterialCode("MAT" + String.format("%06d", i % 100000));
            material.setMaterialName("物料_" + i % 10000);

            // 随机物料类别，影响数量和单位
            String category = randomElement(MATERIAL_CATEGORIES);
            material.setMaterialCategory(category);

            // 根据物料类别设置数量和单位
            if (category.equals("原料")) {
                material.setInventoryQuantity(randomDouble(100, 10000));
                material.setUnit(randomElement(new String[]{"千克", "米", "升"}));
            } else if (category.equals("辅料")) {
                material.setInventoryQuantity(randomDouble(10, 1000));
                material.setUnit(randomElement(new String[]{"件", "箱", "包", "捆"}));
            } else { // 半成品
                material.setInventoryQuantity(randomDouble(1, 500));
                material.setUnit(randomElement(new String[]{"件", "箱"}));
            }

            material.setSpecs("规格_" + random.nextInt(100));

            // 批次号，格式：YYMMDD-序号
            LocalDateTime entryDate = randomDate(2020, 2025);
            SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
            DateTimeFormatter yyMMdd = DateTimeFormatter.ofPattern("yyMMdd");
            String batchDatePart = entryDate.format(yyMMdd);
            material.setBatchCode(batchDatePart + "-" + random.nextInt(1000));

            material.setDisable(0);//random.nextInt(2)

            // 随机选择厂商
            material.setManufacturers(randomElement(MANUFACTURERS));

            // 为物料分配载具和仓库
            ContainerDao container = randomElement(containers);
            material.setContainerCode(container.getId());

            // 根据载具类型设置物料类型
            if (container.getType().equals("料箱")) {
                material.setMaterial("实体物料");
            } else {
                material.setMaterial(randomElement(MATERIAL_TYPES));
            }

            material.setEntryTime(entryDate);
            material.setSupplierCustomer("供应商_" + random.nextInt(100));

            // 根据载具找对应的仓库
            StoreLocalDao store = findStoreByContainerCode(container.getId(), stores);
            if (store != null) {
                material.setWarehouse(store.getFloor());
                material.setIssuePosition(store.getId());
            } else {
                // 如果找不到对应的储位，随机分配一个仓库
                String warehouse = randomElement(WAREHOUSES);
                material.setWarehouse(warehouse);

                // 随机选择该仓库下的一个储位
                List<StoreLocalDao> warehouseStores = storesByWarehouse.get(warehouse);
                if (!warehouseStores.isEmpty()) {
                    StoreLocalDao randomStore = randomElement(warehouseStores);
                    material.setIssuePosition(randomStore.getId());
                }
            }
            LocalDateTime dateTime = Instant.ofEpochMilli(new Date().getTime())
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
            material.setOperator(randomElement(OPERATORS));
            material.setOperationTime(dateTime);
            material.setColor(randomElement(COLORS));
            material.setMeasurementMethod(randomElement(MEASUREMENT_METHODS));
            material.setMeedleCount("针数_" + random.nextInt(300));
            material.setSize("尺寸_" + random.nextInt(50));
            material.setSizePage("尺寸页_" + random.nextInt(10));
            material.setWorkingNo("工序号_" + random.nextInt(100));
            material.setProductType("产品类型_" + random.nextInt(50));
            material.setPackagingMethod(randomElement(PACKAGING_METHODS));
            material.setSpecialProcess("特殊工艺_" + random.nextInt(20));
            material.setProgramName("程式_" + random.nextInt(50));
            material.setWeavingMachine("织机_" + random.nextInt(30));
            material.setHcbanderole("HCB_" + random.nextInt(100));
            material.setComposition("成分_" + random.nextInt(30));
            material.setQclab("质检实验室_" + random.nextInt(10));
            material.setPackagingRatio(random.nextInt(100) + ":1");
            material.setPurchaseOrder(String.valueOf(SnowIdUtil.nextId()));
            materials.add(material);
        }
        return materials;
    }

    private static StoreLocalDao findStoreByContainerCode(String containerCode, List<StoreLocalDao> stores) {
        for (StoreLocalDao store : stores) {
            if (containerCode.equals(store.getContainerCode())) {
                return store;
            }
        }
        return null;
    }

    private static <T> T randomElement(T[] array) {
        return array[random.nextInt(array.length)];
    }

    private static <T> T randomElement(List<T> list) {
        return list.get(random.nextInt(list.size()));
    }

    private static double randomDouble(double min, double max) {
        return Math.round(min + (max - min) * random.nextDouble() * 100.0) / 100.0;
    }

    public static LocalDateTime randomDate(int startYear, int endYear) {
        long startMillis = new GregorianCalendar(startYear, 0, 1).getTimeInMillis();
        long endMillis = new GregorianCalendar(endYear, 11, 31).getTimeInMillis();
        long randomMillis = startMillis + (long) (random.nextDouble() * (endMillis - startMillis));
        // 方式1：通过Instant和系统默认时区
        LocalDateTime dateTime = Instant.ofEpochMilli(randomMillis)
                .atZone(ZoneId.systemDefault())
                .toLocalDateTime();
        return dateTime;
    }

    private static Date randomDate1(int startYear, int endYear) {
        long startMillis = new GregorianCalendar(startYear, 0, 1).getTimeInMillis();
        long endMillis = new GregorianCalendar(endYear, 11, 31).getTimeInMillis();
        long randomMillis = startMillis + (long) (random.nextDouble() * (endMillis - startMillis));
        return new Date(randomMillis);
    }

    private static void writeContainersToCsv(List<ContainerDao> containers, String fileName) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
            // 写入CSV头部
            writer.write("id,type,local,disable,is_exist,bar_code_bad,container_bad,abnormal_date,weight,create_date,update_date,w_long,w_wide,w_tall\n");

            // 写入数据
            for (ContainerDao container : containers) {
                writer.write(String.format("%s,%s,%s,%d,%d,%d,%d,%s,%f,%s,%s,%f,%f,%f\n",
                        container.getId(),
                        container.getType(),
                        container.getLocal(),
                        container.getDisable(),
                        container.getIsExist(),
                        container.getBarCodeBad(),
                        container.getContainerBad(),
                        container.getAbnormalDate() != null ? container.getAbnormalDate() : "",
                        container.getWeight(),
                        container.getCreateDate(),
                        container.getUpdateDate(),
                        container.getWLong(),
                        container.getWWide(),
                        container.getWTall()
                ));
            }
        }
    }

    private static void writeStoresToCsv(List<StoreLocalDao> stores, String fileName) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
            // 写入CSV头部
            writer.write("id,store_name,floor,region,frame,serial,ware_type,store_type,good_type,status,is_lock,is_door,container_code,create_date,update_date,weight,s_long,s_wide,s_tall\n");

            // 写入数据
            for (StoreLocalDao store : stores) {
                writer.write(String.format("%s,%s,%s,%s,%s,%s,%s,%s,%s,%d,%d,%d,%s,%s,%s,%f,%f,%f,%f\n",
                        store.getId(),
                        store.getStoreName(),
                        store.getFloor(),
                        store.getRegion(),
                        store.getFrame(),
                        store.getSerial(),
                        store.getWareType(),
                        store.getStoreType(),
                        store.getGoodType(),
                        store.getStatus(),
                        store.getIsLock(),
                        store.getContainerCode() != null ? store.getContainerCode() : "",
                        store.getCreateDate(),
                        store.getUpdateDate(),
                        store.getWeight(),
                        store.getSLong(),
                        store.getSWide(),
                        store.getSTall()
                ));
            }
        }
    }

    private static void writeMaterialsToCsv(List<MaterialDao> materials, String fileName) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
            // 写入CSV头部
            writer.write("item_bar_code,material_code,material_name,inventory_quantity,unit,specs,batch_code,disable,manufacturers,container_code,material_category,material,entry_time,supplier_customer,warehouse,issue_position,operator,operation_time,color,measurement_method,meedle_count,size,size_page,working_no,product_type,packaging_method,special_process,program_name,weaving_machine,hcbanderole,composition,qclab,packaging_ratio\n");

            // 写入数据
            for (MaterialDao material : materials) {
                writer.write(String.format("%s,%s,%s,%f,%s,%s,%s,%d,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
                        material.getItemBarCode(),
                        material.getMaterialCode(),
                        material.getMaterialName(),
                        material.getInventoryQuantity(),
                        material.getUnit(),
                        material.getSpecs(),
                        material.getBatchCode(),
                        material.getDisable(),
                        material.getManufacturers(),
                        material.getContainerCode(),
                        material.getMaterialCategory(),
                        material.getMaterial(),
                        material.getEntryTime(),
                        material.getSupplierCustomer(),
                        material.getWarehouse(),
                        material.getIssuePosition(),
                        material.getOperator(),
                        material.getOperationTime(),
                        material.getColor(),
                        material.getMeasurementMethod(),
                        material.getMeedleCount(),
                        material.getSize(),
                        material.getSizePage(),
                        material.getWorkingNo(),
                        material.getProductType(),
                        material.getPackagingMethod(),
                        material.getSpecialProcess(),
                        material.getProgramName(),
                        material.getWeavingMachine(),
                        material.getHcbanderole(),
                        material.getComposition(),
                        material.getQclab(),
                        material.getPackagingRatio()
                ));
            }
        }
    }
}    